package com.factory.code.service.impl;

import com.factory.code.controller.param.TemplatePageParam;
import com.factory.code.controller.vo.PageVO;
import com.factory.code.controller.vo.R;
import com.factory.code.lib.CustomTemplateManager;
import com.factory.code.repository.ProjectRepository;
import com.factory.code.repository.TemplateCustomRepository;
import com.factory.code.repository.ent.TemplateCustomENT;
import com.factory.code.service.TemplateCustomService;
import com.factory.code.service.model.CodeTableModel;
import com.factory.code.service.model.CodeVelocityModel;
import com.factory.code.service.model.NameAndValueModel;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.VelocityContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;

/**
 * @author
 */
@Service
public class TemplateCustomServiceImpl implements TemplateCustomService {
    private static final Logger logger = LoggerFactory.getLogger(TemplateServiceImpl.class);

    @Autowired
    private ProjectRepository projectRepository;

    @Autowired
    private TemplateCustomRepository templateCustomRepository;
    @Autowired
    private CustomTemplateManager customTemplateManager;


    @Override
    public PageVO<TemplateCustomENT> getPage(TemplatePageParam param) {
        Sort.Direction sort = Sort.Direction.DESC;
        Pageable pageable = PageRequest.of(param.getCurrentPage() - 1, param.getPageSize(), sort, "id");
        Specification specification = (Specification) (root, criteriaQuery, cb) -> {
            //增加筛选条件
            Predicate predicate = cb.conjunction();
            if (param.getProjectId() != null) {
                predicate.getExpressions().add(cb.equal(root.get("projectId"), param.getProjectId()));
            }
            if (StringUtils.isNotBlank(param.getName())) {
                predicate.getExpressions().add(cb.like(root.get("name"), "%" + param.getName() + "%"));
            }
            return predicate;
        };
        Page<TemplateCustomENT> pageList = templateCustomRepository.findAll(specification, pageable);
        PageVO vo = new PageVO();
        vo.setTotal(pageList.getTotalElements());
        vo.setRecords(pageList.getContent());
        return vo;
    }

    @Override
    public R<List<NameAndValueModel>> getJavaMethodList() {
        List<NameAndValueModel> methodList = customTemplateManager.getMethodList();
        return R.ok(methodList);
    }

    @Override
    public List<TemplateCustomENT> listByProjectId(Integer projectId) {
        return templateCustomRepository.findByProjectId(projectId);
    }

    @Override
    public TemplateCustomENT getById(Integer id) {
        TemplateCustomENT one = templateCustomRepository.getById(id);
        return one;
    }

    @Override
    public R update(TemplateCustomENT customENT) {
        Integer samples = projectRepository.getSamplesById(customENT.getProjectId());
        if (samples != null && samples == 1) {
            return R.fail("示例不能操作");
        }
        templateCustomRepository.saveAndFlush(customENT);
        return R.ok();
    }

    @Override
    public R add(TemplateCustomENT customENT) {
        Integer samples = projectRepository.getSamplesById(customENT.getProjectId());
        if (samples != null && samples == 1) {
            return R.fail("示例不能操作");
        }
        templateCustomRepository.saveAndFlush(customENT);
        return R.ok();
    }

    @Override
    public R delete(TemplateCustomENT customENT) {
        Integer samples = projectRepository.getSamplesById(customENT.getProjectId());
        if (samples != null && samples == 1) {
            return R.fail("示例不能操作");
        }
        templateCustomRepository.deleteById(customENT.getId());
        return R.ok();
    }


    /**
     * 自定义 模板 可放代码块
     *
     * @param projectId
     * @return
     */
    @Override
    public CodeVelocityModel getCustomTemplate(Integer projectId) {
        List<TemplateCustomENT> customENTS = templateCustomRepository.findByProjectId(projectId);
        CodeVelocityModel model = new CodeVelocityModel();
        model.setText("自定义 模板");
        model.setExpression("");
        List<CodeVelocityModel> list = new ArrayList<>();
        for (TemplateCustomENT customENT : customENTS) {
            list.add(new CodeVelocityModel(String.format("${%s}", customENT.getExpression()), customENT.getText()));
        }
        model.setChildren(list);
        return model;
    }

    /**
     * 设置自定义模板
     *
     * @param projectId
     * @param context
     * @return
     */
    @Override
    public VelocityContext setCustomTemplateContent(Integer projectId, VelocityContext context, CodeTableModel tableModel) {
        List<TemplateCustomENT> customENTS = templateCustomRepository.findByProjectId(projectId);
        for (TemplateCustomENT customENT : customENTS) {
            if (customENT.getType() != null && customENT.getType() == 1) {
                String content = customTemplateManager.executeMethod(customENT.getMethod(), customENT.getParam(), tableModel);
                context.put(customENT.getExpression(), content);
            } else {
                context.put(customENT.getExpression(), customENT.getContent());
            }
        }
        return context;
    }


}
